﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using cludg.Repository.Transactions;
using cludg.Web.RateContentModule.Domain;
using cludg.Web.RateContentModule.Repository;
using cludg.Domain.Users;
using cludg.Domain.Content.Stories;
using cludg.Repository.Content;

namespace cludg.Web.RateContentModule.Services
{
	public class RateService
	{
		protected readonly IRateRepository RateRepository;
		protected readonly ITransactionFactory TransactionFactory;
		protected readonly IContentRepository<Story> StoryRepository;

		public RateService(
			IRateRepository rateRepository,
			ITransactionFactory transactionFactory,
			IContentRepository<Story> storyRepository)
		{
			RateRepository = rateRepository;
			TransactionFactory = transactionFactory;
			StoryRepository = storyRepository;
		}

		public bool HasUserRate(User user, Story story)
		{
			return RateRepository.HasForUser(user, story);
		}

		public Domain.RateHistory Get(User user, Story story)
		{
			return RateRepository.GetForUser(user, story);
		}

		public void Rate(User user, Story story, int rate)
		{
			using (var tran = TransactionFactory.BeginTransaction())
			{
				int pos, neg;
				GetStorySummary(story, out pos, out neg);
				int newRate = pos + neg + rate;

				var history = Get(user, story);
				if (history != null)
				{
					history.Rerate(rate);
					RateRepository.Save(history);

					story.Rate = newRate + rate;
				}
				else
				{
					history = new RateHistory(user, story, rate);
					RateRepository.Add(history);

					story.Rate = newRate;
				}

				StoryRepository.Save(story);

				tran.Commit();
			}
		}

		public void GetStorySummary(Story story, out int positive, out int negative)
		{
			var all = RateRepository.AllForStory(story);
			positive = all.Where(x => x.Rate > 0).Sum(x => x.Rate);
			negative = all.Where(x => x.Rate < 0).Sum(x => x.Rate);
		}

		public IEnumerable<Story> TopRatedStories(int count)
		{
			return StoryRepository.Get().OrderByDescending(x => x.Rate).Take(count);
		}
	}
}